/*
MIT License 

Copyright (c) 2021 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов, 

https://bmstu.codes/lsx/simodo/loom
*/

#ifndef simodo_fuze_StBuilder
#define simodo_fuze_StBuilder

/*! \file AstFormationBuilder.h
    \brief Построитель семантического дерева
*/

#include "simodo/interpret/builtins/hosts/base/BaseInterpret_abstract.h"
#include "simodo/interpret/builtins/modules/AstFormationModule.h"
#include "simodo/interpret/Interpret.h"
#include "simodo/parser/automaton/AstBuilder_interface.h"
#include "simodo/parser/SyntaxDataCollector_interface.h"
#include "simodo/inout/reporter/Reporter_abstract.h"

#include <string>
#include <memory>

namespace simodo::interpret::builtins
{
    /*!
     * \brief Построитель абстрактного синтаксического дерева (АСД) для выражений
     *
     * \attention Данный класс имеет формируемое состояние, копирование нужно делать аккуратно.
     */
    class AstFormationBuilder: public parser::AstBuilder_interface
    {
        inout::Reporter_abstract &              _m;
        BaseInterpret_abstract &                _sbl_host;
        std::shared_ptr<AstFormationModule>     _ast_formation_module;
        variable::VariableSet_t &               _hosts;
        parser::SyntaxDataCollector_interface & _syntax_data_collector;

    public:
        AstFormationBuilder() = delete;              ///< Пустой конструктор не поддерживается!

        /*!
         * \brief Инициализирующий конструктор построителя АСД выражений
         * \param reporter Обработчик сообщений
         * \param sbl_host Интерпретатор кода семантических вставок
         */
        AstFormationBuilder(inout::Reporter_abstract & reporter, 
                            BaseInterpret_abstract & sbl_host,
                            variable::VariableSet_t & hosts);

        /*!
         * \brief Инициализирующий конструктор построителя АСД выражений
         * \param reporter Обработчик сообщений
         * \param sbl_host Интерпретатор кода семантических вставок
         * \param syntax_data_collector Коллектор сбора синтаксических данных для последующего анализа
         */
        AstFormationBuilder(inout::Reporter_abstract & reporter, 
                            BaseInterpret_abstract & sbl_host,
                            variable::VariableSet_t & hosts,
                            parser::SyntaxDataCollector_interface & syntax_data_collector);

        virtual ~AstFormationBuilder();

        inout::Reporter_abstract &      reporter()                      { return _m; }
        ast::FormationFlow_interface &  ast()                           { return (*_ast_formation_module)(); }
        bool                            weave(const ast::Node & code);

        /*!
         * \brief Метод вызывается парсером перед началом разбора
         * \return Если возвращается false, парсер прекращает разбор с ошибкой, иначе - продолжает
         */
        virtual bool onStart(const std::map<std::u16string,ast::Node> & handlers) override;

#ifdef AST_BUILDER_DEBUG
        /*!
         * \brief Метод вызывается парсером при выполнении свёртки
         *
         * Метод вызывается, когда выполняется свёртка состояний.
         *
         * \param state_no      Номер состояния
         * \param rule_no       Номер правила
         * \param production    Токен продукции, на которую заменяется шаблон в стеке состояний парсера
         * \param pattern       Шаблон (набор токенов), который заменяется на продукцию в стеке состояний парсера
         * \param action        АСД для интерпретатора для формирования фрагмента АСД по данной продукции
         * \param back_state_no Номер состояния возврата после свёртки
         * \param shift_state_no Номер состояния перехода после свёртки
         * \return Если возвращается false, парсер прекращает разбор с ошибкой, иначе - продолжает
         */
        virtual bool onProduction(size_t state_no,
                                  size_t rule_no,
                                  const inout::Token & production,
                                  const std::vector<inout::Token> & pattern,
                                  const ast::Node & action,
                                  size_t back_state_no,
                                  size_t shift_state_no) override;

        virtual bool onShift(size_t , const inout::Lexeme & , size_t , size_t ) override { return true; }
#else
        /*!
         * \brief Метод вызывается парсером при выполнении свёртки
         *
         * Метод вызывается, когда выполняется свёртка состояний.
         *
         * \param production    Токен продукции, на которую заменяется шаблон в стеке состояний парсера
         * \param pattern       Шаблон (набор токенов), который заменяется на продукцию в стеке состояний парсера
         * \param action        АСД для интерпретатора для формирования фрагмента АСД по данной продукции
         * \return Если возвращается false, парсер прекращает разбор с ошибкой, иначе - продолжает
         */
        virtual bool onProduction(const inout::Token & production,
                                  const std::vector<inout::Token> & pattern,
                                  const ast::Node & action) override;
#endif
        /*!
         * \brief Метод вызывается парсером при получении очередного токена
         * \param token Текущий обрабатываемый токен входного потока
         */
        virtual void onTerminal(const inout::Token & token) override;

        /*!
         * \brief Метод вызывается парсером после завершения разбора текста
         *
         * Предполагается, что при вызове данного метода и при наличии признака успешности
         * разбора текста, нужно завершить формирование АСД.
         *
         * \return Если возвращается false, парсер прекращает разбор с ошибкой, иначе - продолжает
         */
        virtual bool onFinish(bool, const std::map<std::u16string,ast::Node> & handlers) override;

    protected:

    };

}

#endif // simodo_fuze_StBuilder

